package cn.yangliu.comm.tools;

import cn.yangliu.comm.annotation.EqualField;
import cn.yangliu.comm.annotation.TargetField;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * Created by 杨柳 on 2016/8/5 0005.
 * email:yangliu@buestc.com
 * tel:18523437817
 */
public class ObjectUtils {

    public static <T> T newInstance(Object oldData, Class<T> target) {
        Object obj;
        try {
            obj = target.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(),e);
        }
        return (T) copyFiedValue(oldData, obj);
    }

    public static <T> List<T> newInstances(List<?> dataList, Class<T> target) {
        List<T> list = dataList.parallelStream().collect(ArrayList<T>::new, (list1, item) -> {
            T t = newInstance(item, target);
            list1.add(t);
        }, (list2, list3) -> list2.addAll(list3));

       /* List<T> list = new ArrayList<>();
        for (Object o : dataList) {
            T t = newInstance(o, target);
            list.add(t);
        }*/
        return list;
    }

    /**
     * @param target    目标类型
     * @param mainDatas 主数据
     * @param dataLists 从数据
     *                  主数据保留,如果从数据没有 则舍弃
     */
    public static <T> List<T> newInstances(Class<T> target, List<?> mainDatas, List<Object>... dataLists) {

        List<T> dataList = new ArrayList<>();

        mainDatas.parallelStream().peek(mainData -> {
            T t = newInstance(mainData, target);
            Object mainDataEqualValue = findEqualField(mainData);
            dataList.add(t);
            if (mainDataEqualValue != null) {// 如果为空 则直接复制主数据到dto
                copyFiedValue(mainData, t);
                //循环从数据List
                for (List<Object> list : dataLists) {
                    list.parallelStream().peek(data -> {
                        Object dataEqualValue = findEqualField(data);
                        if (mainDataEqualValue.equals(dataEqualValue)) { //两个值相等 说明有关联性
                            copyFiedValue(data, t);
                        }
                    });
                }
            }

        }).count();

       /* for (Object mainData : mainDatas) {
            T t = newInstance(mainData, target);
            Object mainDataEqualValue = findEqualField(mainData);
            dataList.add(t);
            if (mainDataEqualValue == null) {// 如果为空 则直接复制主数据到dto
                copyFiedValue(mainData, t);
                continue;
            }
            //循环从数据List
            for (List<Object> list : dataLists) {
                for (Object data : list) { //从数据
                    Object dataEqualValue = findEqualField(data);
                    if (mainDataEqualValue.equals(dataEqualValue)) { //两个值相等 说明有关联性
                        copyFiedValue(data, t);
                    }
                }
            }

        }
*/
        return dataList;
    }

    private static Object findEqualField(Object obj) {
        //主数据所有的属性
        // List<Field> fields = ReflectUtils.getFields(obj.getClass(), Object.class);
        Object value = null; //相等值

        /*----------------*/
        Class<?> clazz = obj.getClass();
       /* boolean flag = true;*/
        while (clazz != null && clazz != Object.class) {//当父类为null的时候说明到达了最上层的父类(Object类).
            List<Field> fields = Arrays.asList(clazz.getDeclaredFields());
            Field field=fields.parallelStream().filter(item -> ReflectUtils.getFieldAnnotation(item, EqualField.class) != null).findAny().orElse(null);
            if (field!=null){
                value = ReflectUtils.getValueByGetMethod(field, obj);
                break;
            }
           /* for (Field field : fields) {
                if (ReflectUtils.getFieldAnnotation(field, EqualField.class) != null) {
                    value = ReflectUtils.getValueByGetMethod(field, obj);
                    flag = false;
                    break;
                }
            }*/
           /* if (flag) {
                break;
            }*/
            clazz = clazz.getSuperclass(); //得到父类,然后赋给自己
        }

    /*--------------------*/
      /*  for (Field field : fields) {
            if (ReflectUtils.getFieldAnnotation(field, EqualField.class) != null) {
                value = ReflectUtils.getValueByGetMethod(field, obj);
                break;
            }
        }*/
        return value;
    }

    public static <T> T copyFiedValue(Object oldData, T target) {
        List<Field> fields = ReflectUtils.getFields(oldData.getClass(), Object.class);

        fields.parallelStream().peek(field -> {
            Annotation annotation = field.getAnnotation(TargetField.class);
            if (annotation != null) {

                String annotationValue = ReflectUtils.getAnnotationValue("value", annotation);
                //是否转换成string
                boolean trans2String = ReflectUtils.getAnnotationValue("trans2string", annotation);
                String datePattern = ReflectUtils.getAnnotationValue("datePattern", annotation);

                //数字或者其他的类型
                boolean isOther = ReflectUtils.getAnnotationValue("isOther", annotation);

                //缩放率
                int otherTrans = ReflectUtils.getAnnotationValue("otherTrans", annotation);
                //金额格式化?
                boolean moneyFormat = ReflectUtils.getAnnotationValue("moneyFormat", annotation);

                if ("".equals(annotationValue)) {
                    //新旧名字一样
                    //获取 目标对象的属性
                    Field targetField = ReflectUtils.getField(field.getName(), target);
                    //获取原对象属性的值
                    Object oldFieldValue = ReflectUtils.getValueByGetMethod(field, oldData);
                    //给目标类型对象的属性赋值
                    setValue(target, trans2String, datePattern, isOther, otherTrans, moneyFormat, targetField, oldFieldValue);
                } else {
                    //新旧名字不一样
                    Field newField = ReflectUtils.getField(annotationValue, target);
                    Object oldFieldValue = ReflectUtils.getValueByGetMethod(field, oldData);

                    setValue(target, trans2String, datePattern, isOther, otherTrans, moneyFormat, newField, oldFieldValue);
                }
            }
        }).count();
       /* for (Field field : fields) {
            Annotation annotation = field.getAnnotation(TargetField.class);
            if (annotation == null) {
                continue;
            }
            String annotationValue = ReflectUtils.getAnnotationValue("value", annotation);
            //是否转换成string
            boolean trans2String = ReflectUtils.getAnnotationValue("trans2string", annotation);
            String datePattern = ReflectUtils.getAnnotationValue("datePattern", annotation);

            //数字或者其他的类型
            boolean isOther = ReflectUtils.getAnnotationValue("isOther", annotation);

            //缩放率
            int otherTrans = ReflectUtils.getAnnotationValue("otherTrans", annotation);
            //金额格式化?
            boolean moneyFormat = ReflectUtils.getAnnotationValue("moneyFormat", annotation);

            if ("".equals(annotationValue)) {
                //新旧名字一样
                //获取 目标对象的属性
                Field targetField = ReflectUtils.getField(field.getName(), target);
                //获取原对象属性的值
                Object oldFieldValue = ReflectUtils.getValueByGetMethod(field, oldData);
                //给目标类型对象的属性赋值
                setValue(target, trans2String, datePattern, isOther, otherTrans, moneyFormat, targetField, oldFieldValue);
            } else {
                //新旧名字不一样
                Field newField = ReflectUtils.getField(annotationValue, target);
                Object oldFieldValue = ReflectUtils.getValueByGetMethod(field, oldData);

                setValue(target, trans2String, datePattern, isOther, otherTrans, moneyFormat, newField, oldFieldValue);
            }
        }*/
        return target;
    }

    private static <T> void setValue(T target, boolean trans2String, String datePattern, boolean isOther, int otherTrans, boolean moneyFormat, Field newField, Object oldFieldValue) {
        if (oldFieldValue != null) {
            oldFieldValue = check(isOther, otherTrans, moneyFormat, oldFieldValue);
            if (trans2String) {
                ReflectUtils.setValueBySetMethod(newField, target, getStringValue(oldFieldValue, datePattern));
            } else {
                ReflectUtils.setValueBySetMethod(newField, target, oldFieldValue);
            }
        }
    }

    private static Object check(boolean isOther, int otherTrans, boolean moneyFormat, Object oldFieldValue) {
        if (isOther) { //其他类型? 是
            BigDecimal bigDecimal = new BigDecimal(oldFieldValue.toString());
            BigDecimal rate = new BigDecimal(otherTrans);
            bigDecimal = bigDecimal.divide(rate);
            oldFieldValue = bigDecimal;
            if (moneyFormat) {//金额格式化?
                oldFieldValue = StringUtils.formartAmountToStr(bigDecimal);
            }
        }
        return oldFieldValue;
    }



    public static boolean instansOf(Class<?> fieldType, Class<?> targetClass) {
        if (fieldType == Object.class && targetClass == Object.class) {
            return true;
        }
        do {
            if (fieldType == targetClass) {
                return true;
            }
            fieldType = fieldType.getSuperclass();
        } while (fieldType != Object.class);
        return false;
    }

    private static String getStringValue(Object value, String datePattern) {
        String valueString = "";
        if (value == null) {
            return valueString;
        }
        if (value instanceof Number) {
            valueString += value;
        } else if (value instanceof Date) {
            Date date = (Date) value;
            valueString = DateUtils.date2String(date, datePattern);
        } else if (value instanceof String) {
            valueString = (String) value;
        }
        return valueString;
    }

}
